package com.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.ZjWorkFeeDetail;
import com.zb.entity.ZjWorkFeeDetailImage;
import com.zb.entity.ZjWorkFeeProject;
import com.zb.extend.WorkFeeDetailExtend;
import com.zb.mapper.ZjWorkFeeDetailMapper;
import com.zb.mobile.NetworkMobileApplyOrderFeeDetailVo;
import com.zb.service.ZjWorkFeeDetailImageService;
import com.zb.service.ZjWorkFeeDetailService;
import com.zb.service.ZjWorkFeeProjectService;
import com.zb.vo.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 工单费用信息表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-10-25
 */
@Service
public class ZjWorkFeeDetailServiceImpl extends ServiceImpl<ZjWorkFeeDetailMapper, ZjWorkFeeDetail> implements ZjWorkFeeDetailService {
    @Resource
    private ZjWorkFeeDetailMapper workFeeDetailMapper;
    @Resource
    private ZjWorkFeeProjectService workFeeProjectService;
    @Resource
    private ZjWorkFeeDetailImageService workFeeDetailImageService;


    // 保存、修改、删除工单费用详情
    @Override
    public void save(Long custAccId, Long workFeeId, Long workId, List<WorkFeeDetailVo> feeDetails, List<Long> ids) {
        if (CollectionUtil.isNotEmpty(ids)) {
            workFeeDetailImageService.deleteByWorkFeeDetailId(ids);
            this.removeByIds(ids);
        }
        List<ZjWorkFeeProject> feeProjects = workFeeProjectService.listByIds(feeDetails.stream().map(WorkFeeDetailVo::getWorkFeeProjectId).distinct().toList());
        List<String> feeProjectIds = feeDetails.stream().map(WorkFeeDetailVo::getWorkFeeProjectId).filter(workFeeProjectId -> feeProjects.stream().noneMatch(pro -> Objects.equals(pro.getId(), workFeeProjectId))).map(String::valueOf).distinct().toList();
        Assert.isTrue(CollectionUtil.isEmpty(feeProjectIds), "工单费用项目["+ String.join("、", feeProjectIds) +"]的数据不存在系统中，请排查后重试");

        QueryWrapper<ZjWorkFeeDetail> wrapper = new QueryWrapper<>();
        wrapper.select("id", "type", "work_fee_project_id", "pay_network_price", "receive_factory_price", "qty");
        wrapper.eq("work_fee_id", workFeeId);
        List<ZjWorkFeeDetail> feeDetailList = this.list(wrapper);
        if (CollectionUtil.isNotEmpty(feeDetailList)) {
            feeDetails.forEach(t -> {
                if (null == t.getId()) {
                    Long id = feeDetailList.stream().filter(f -> Objects.equals(f.getType(), t.getType()) && Objects.equals(f.getWorkFeeProjectId(), t.getWorkFeeProjectId()) &&
                                    Objects.equals(f.getPrice(), t.getPrice()) && Objects.equals(f.getPayNetworkPrice(), t.getPayNetworkPrice()) && Objects.equals(f.getReceiveFactoryPrice(), t.getReceiveFactoryPrice()))
                            .map(ZjWorkFeeDetail::getId).findFirst().orElse(null);
                    if (null != id) {
                        t.setId(id);
                    }
                }
            });
        }
        List<WorkFeeDetailVo> newFeeDetailList = new ArrayList<>(feeDetails.stream().filter(f -> null != f.getId()).toList());
        newFeeDetailList.forEach(feeDetails::remove);
        feeDetails.forEach(t -> {
            if (newFeeDetailList.stream().anyMatch(f -> Objects.equals(f.getType(), t.getType()) && Objects.equals(f.getWorkFeeProjectId(), t.getWorkFeeProjectId()) &&
                    Objects.equals(f.getPrice(), t.getPrice()) && Objects.equals(f.getPayNetworkPrice(), t.getPayNetworkPrice()) && Objects.equals(f.getReceiveFactoryPrice(), t.getReceiveFactoryPrice()))) {
                newFeeDetailList.forEach(k -> {
                    if (Objects.equals(k.getType(), t.getType()) &&  Objects.equals(k.getWorkFeeProjectId(), t.getWorkFeeProjectId()) &&
                            Objects.equals(k.getPayNetworkPrice(), t.getPayNetworkPrice()) && Objects.equals(k.getReceiveFactoryPrice(), t.getReceiveFactoryPrice())) {
                        k.setQty(k.getQty() + t.getQty());
                        if (CollectionUtil.isNotEmpty(t.getDelImageIds())) {
                            if (CollectionUtil.isNotEmpty(k.getDelImageIds())) {
                                k.getDelImageIds().addAll(t.getDelImageIds());
                            } else {
                                k.setDelImageIds(t.getDelImageIds());
                            }
                        }
                        if (CollectionUtil.isNotEmpty(t.getImages())) {
                            if (CollectionUtil.isNotEmpty(k.getImages())) {
                                k.getImages().addAll(t.getImages());
                            } else {
                                k.setImages(t.getImages());
                            }
                        }
                    }
                });
                return;
            }
            newFeeDetailList.add(t);
        });

        List<ZjWorkFeeDetail> adds = new ArrayList<>();
        List<ZjWorkFeeDetail> updates = new ArrayList<>();
        List<ZjWorkFeeDetailImage> images = new ArrayList<>();
        List<Long> delImageIds = new ArrayList<>();
        ZjWorkFeeDetail detail = null;
        ZjWorkFeeDetailImage detailImage = null;
        for (WorkFeeDetailVo vo : newFeeDetailList) {
            detail = new ZjWorkFeeDetail();
            BeanUtil.copyProperties(vo, detail);
            detail.setSurePriceStatus(0);
            if (null != detail.getId()) {
                updates.add(detail);
            } else {
                detail.setId(IdWorker.getId());
                detail.setCustAccId(custAccId);
                detail.setWorkFeeId(workFeeId);
                detail.setWorkId(workId);
                detail.setStatus(1);
                adds.add(detail);
            }
            if (CollectionUtil.isNotEmpty(vo.getDelImageIds())) {
                delImageIds.addAll(vo.getDelImageIds());
            }
            for (OrderImageVo image : vo.getImages()) {
                if (null == image.getId()) {
                    detailImage = new ZjWorkFeeDetailImage();
                    detailImage.setId(IdWorker.getId());
                    detailImage.setCustAccId(custAccId);
                    detailImage.setWorkFeeDetailId(detail.getId());
                    detailImage.setImage(image.getImage());
                    images.add(detailImage);
                }
            }
        }
        if (CollectionUtil.isNotEmpty(adds)) this.saveBatch(adds);
        if (CollectionUtil.isNotEmpty(updates)) this.updateBatchById(updates);
        if (CollectionUtil.isNotEmpty(delImageIds)) workFeeDetailImageService.removeByIds(delImageIds);
        if (CollectionUtil.isNotEmpty(images)) workFeeDetailImageService.saveBatch(images);
    }

    // 保存移动端服务商申请工单费用
    @Override
    public void saveMobileNetworkFee(Long custAccId, Long workFeeId, Long workId, List<NetworkMobileApplyOrderFeeDetailVo> orderFeeDetailVos) {
        save(custAccId, workFeeId, workId, orderFeeDetailVos.stream().map(feeDetail -> {
            WorkFeeDetailVo vo = new WorkFeeDetailVo();
            BeanUtil.copyProperties(feeDetail, vo);
            vo.setNetworkApply(true);
            vo.setImages(feeDetail.getIamges().stream().map(s -> {
                return new OrderImageVo(null, null == s? "" : s);
            }).toList());
            return vo;
        }).toList(), null);
    }

    // 根据工单费用表ID获取工单费用信息
    @Override
    public List<WorkFeeDetailExtend> getByWorkFeedIds(List<Long> workFeeIds) {
        if (CollectionUtil.isEmpty(workFeeIds)) {
            return new ArrayList<>();
        }
        QueryWrapper<ZjWorkFeeDetail> wrapper = new QueryWrapper<>();
        wrapper.select("id", "work_fee_id", "type", "work_fee_project_id", "sure_price_status", "price", "pay_network_price", "receive_factory_price", "qty", "status");
        wrapper.in("work_fee_id", workFeeIds);
        List<ZjWorkFeeDetail> detailList = this.list(wrapper);
        List<ZjWorkFeeProject> projectList = workFeeProjectService.listByIds(detailList.stream().map(ZjWorkFeeDetail::getWorkFeeProjectId).distinct().toList());
        return detailList.stream().map(fee -> {
            WorkFeeDetailExtend extend = new WorkFeeDetailExtend();
            BeanUtil.copyProperties(fee, extend);
            extend.setName(projectList.stream().filter(f -> Objects.equals(f.getId(), fee.getWorkFeeProjectId())).map(ZjWorkFeeProject::getName).findFirst().orElse(""));
            return extend;
        }).toList();
    }

    // 根据工单费用表ID获取工单费用信息
    @Override
    public List<WorkFeeDetailExtend> getByWorkFeedId(Long workFeeId) {
        QueryWrapper<ZjWorkFeeDetail> wrapper = new QueryWrapper<>();
        wrapper.select("id", "work_fee_id", "status", "type", "work_fee_project_id", "sure_price_status", "price", "pay_network_price", "receive_factory_price", "qty", "remark");
        wrapper.eq("work_fee_id", workFeeId);
        List<ZjWorkFeeDetail> detailList = this.list(wrapper);
        List<ZjWorkFeeProject> projectList = workFeeProjectService.listByIds(detailList.stream().map(ZjWorkFeeDetail::getWorkFeeProjectId).distinct().toList());
        return detailList.stream().map(fee -> {
            WorkFeeDetailExtend extend = new WorkFeeDetailExtend();
            BeanUtil.copyProperties(fee, extend);
            extend.setName(projectList.stream().filter(f -> Objects.equals(f.getId(), fee.getWorkFeeProjectId())).map(ZjWorkFeeProject::getName).findFirst().orElse(""));
            return extend;
        }).toList();
    }

    // 根据服务项目ID获取服务费用项目详情的项目信息
    @Override
    public List<WorkFeeDetailInfoVo> getOrderFeeDetailProjectInfo(Long workFeeId) {
        List<WorkFeeDetailExtend> extendList = getByWorkFeedId(workFeeId);
        List<ZjWorkFeeDetailImage> imageList = workFeeDetailImageService.getByWorkFeeDetailIds(extendList.stream().map(WorkFeeDetailExtend::getId).toList());

        return extendList.stream().map(feeDetail -> {
            WorkFeeDetailInfoVo vo = new WorkFeeDetailInfoVo();
            BeanUtil.copyProperties(feeDetail, vo);
            vo.setImages(imageList.stream().filter(f -> Objects.equals(f.getWorkFeeDetailId(), feeDetail.getId())).map(image -> {
                return new OrderImageVo(image.getId(), image.getImage());
            }).toList());
            return vo;
        }).toList();
    }

    @Override
    public List<ExpenseRecordVo> getByWorkOrderId(Long workFeeId) {
        return workFeeDetailMapper.getByWorkOrderId(workFeeId);
    }

    // 审核服务费用项目信息
    @Override
    public void checkOrderFee(Long custAccId, OrderFeeCheckVo orderFeeCheckVo) {
        if (CollectionUtil.isEmpty(orderFeeCheckVo.getFeeDetails())) {
            return;
        }
        List<Long> ids = orderFeeCheckVo.getFeeDetails().stream().map(WorkFeeDetailCheckVo::getId).toList();
        List<ZjWorkFeeDetail> feeDetails = this.listByIds(ids);
        List<String> ids2 = orderFeeCheckVo.getFeeDetails().stream().map(WorkFeeDetailCheckVo::getId).filter(f -> feeDetails.stream().noneMatch(fe -> Objects.equals(fe.getId(), f))).map(String::valueOf).toList();
        Assert.isTrue(CollectionUtil.isEmpty(ids2), "审核的服务项目信息ID参数["+ String.join("、", ids2) +"]的数据不存在");

        List<ZjWorkFeeDetail> updates = new ArrayList<>();
        List<ZjWorkFeeDetailImage> images = new ArrayList<>();
        List<Long> delImageIds = new ArrayList<>();
        ZjWorkFeeDetail detail = null;
        ZjWorkFeeDetailImage img = null;
        for (WorkFeeDetailCheckVo feeDetail : orderFeeCheckVo.getFeeDetails()) {
            detail = new ZjWorkFeeDetail();
            BeanUtil.copyProperties(feeDetail, detail);
            updates.add(detail);
            if (CollectionUtil.isNotEmpty(feeDetail.getImages())) {
                for (OrderImageVo image : feeDetail.getImages()) {
                    if (null == image.getId()) {
                        img = new ZjWorkFeeDetailImage();
                        img.setId(IdWorker.getId());
                        img.setCustAccId(custAccId);
                        img.setWorkFeeDetailId(detail.getId());
                        img.setImage(image.getImage());
                        images.add(img);
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(feeDetail.getDelImageIds())) {
                delImageIds.addAll(feeDetail.getDelImageIds());
            }
        }
        this.updateBatchById(updates);
        if (CollectionUtil.isNotEmpty(images)) workFeeDetailImageService.saveBatch(images);
        if (CollectionUtil.isNotEmpty(delImageIds)) workFeeDetailImageService.removeByIds(delImageIds);
    }

    // 根据工单费用项目表ID获取关联的费用项目ID
    @Override
    public List<Long> getByWorkFeeProjectId(List<Long> workFeeProjectIds) {
        if (CollectionUtil.isEmpty(workFeeProjectIds)) {
            return new ArrayList<>();
        }
        QueryWrapper<ZjWorkFeeDetail> wrapper = new QueryWrapper<>();
        wrapper.select("work_fee_project_id");
        wrapper.in("work_fee_project_id", workFeeProjectIds);
        return this.list(wrapper).stream().map(ZjWorkFeeDetail::getWorkFeeProjectId).distinct().toList();
    }

    // 根据工单ID获取工单服务费用（注：根据工单费用ID分组查询）
    @Override
    public List<WorkFeeDetailExtend> getGroupByWorkIds(List<Long> workIds) {
        if (CollectionUtil.isEmpty(workIds)) {
            return new ArrayList<>();
        }
        return workFeeDetailMapper.getGroupByWorkIds(workIds);
    }

    // 根据工单ID获取工单服务费结算价
    @Override
    public ZjWorkFeeDetail getOrderSettlementFeeByWorkId(Long workId) {
        List<Long> workIds = new ArrayList<>();
        workIds.add(workId);
        List<ZjWorkFeeDetail> feeDetailList = getOrderSettlementFeeByWorkId(workIds);
        return feeDetailList.size() == 0? null : feeDetailList.get(0);

    }

    // 根据工单ID获取工单服务费结算价
    @Override
    public List<ZjWorkFeeDetail> getOrderSettlementFeeByWorkId(List<Long> workIds) {
        if (CollectionUtil.isEmpty(workIds)) {
            return new ArrayList<>();
        }
        return workFeeDetailMapper.getOrderSettlementFeeByWorkId(workIds);
    }

    // 根据工单ID获取异常费用，即服务商申请的费用
    @Override
    public List<ZjWorkFeeDetail> getExceptionFeeByWorkIds(List<Long> workIds) {
        if (CollectionUtil.isEmpty(workIds)) {
            return new ArrayList<>();
        }
        return workFeeDetailMapper.getExceptionFeeByWorkIds(workIds);
    }

    // 根据工单ID获取费用信息
    @Override
    public List<WorkFeeDetailExtend> getByWorkId(Long workId) {
        return workFeeDetailMapper.getByWorkId(workId);
    }

    // 根据工单ID & 工单费用项目ID查询
    @Override
    public ZjWorkFeeDetail getByWorkIdAndWorkFeeProjectId(Long workId, Long workFeeProjectId) {
        return workFeeDetailMapper.getByWorkIdAndWorkFeeProjectId(workId, workFeeProjectId);
    }
}
